package utilx

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

// CreateDir 创建单个目录
func CreateDir(dir string) error {
	if !FsIsExist(dir) {
		return os.Mkdir(dir, os.ModePerm)
	}
	return nil
}

// CreateMutiDir 创建多级目录
func CreateMutiDir(path string) error {
	if !FsIsExist(path) {
		return os.MkdirAll(path, os.ModePerm)
	}
	return nil
}

// FsIsExist 判断目录/文件是否存在
func FsIsExist(fs string) bool {
	_, err := os.Stat(fs)
	if err != nil {
		return os.IsExist(err)
	}
	return true
}

// CreateFile 创建文件
func CreateFile(path string, content []byte) error {
	if f, err := os.Create(path); err != nil {
		return err
	} else {
		if _, err := f.Write(content); err != nil {
			return err
		}
		f.Close()
	}
	return nil
}

// FsRemove 删除目录/文件
func FsRemove(path string, force bool) error {
	if force {
		return os.RemoveAll(path)
	} else {
		return os.Remove(path)
	}
}

// CopyFile 拷贝文件
func CopyFile(src, dest string, force bool) error {
	// 如果目标文件已存在
	if FsIsExist(dest) {
		if force {
			if err := FsRemove(dest, false); err != nil {
				return err
			}
		} else {
			return fmt.Errorf("目标文件已存在")
		}
	}

	// 源文件
	source, err := os.Open(src)
	if err != nil {
		return err
	}
	defer source.Close()

	// 目标
	destination, err := os.Create(dest)
	if err != nil {
		return err
	}
	defer destination.Close()

	buf := make([]byte, 1024)
	for {
		// 读取
		n, err := source.Read(buf)
		if err != nil && err != io.EOF {
			return err
		}
		if n == 0 {
			break
		}
		// 写入
		_, err = destination.Write(buf[:n])
		if err != nil {
			return err
		}
	}
	return nil
}

// ReadFile 读取文件内容
func ReadFileToString(filePath string) (string, error) {
	// 打开文件
	f, err := os.Open(filePath)
	if err != nil {
		return "", err
	}
	defer f.Close()

	// 逐行读取&拼接
	s := bufio.NewScanner(f)
	var builder strings.Builder
	line := 0
	for s.Scan() {
		if line > 0 {
			_, _ = builder.WriteString("\n")
		}
		_, _ = builder.WriteString(s.Text())
		line++
	}
	if s.Err() != nil {
		return "", nil
	}

	return builder.String(), nil
}

// MoveFile 移动文件
func MoveFile(srcFile, destFile string) error {
	return os.Rename(srcFile, destFile)
}

// FsList 列举目录中的对象
func FsList(filePath string, hasDir bool) ([]string, error) {
	p, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}

	fis, err := p.ReadDir(0)
	if err != nil {
		return nil, err
	}

	files := make([]string, 0)
	for _, fi := range fis {
		if !hasDir && fi.IsDir() {
			continue
		}
		files = append(files, fi.Name())
	}

	return files, nil
}
